#ifndef SEQIOT_IEC101_H
#define SEQIOT_IEC101_H

#include <stdint.h>
#include <time.h>
#include "asdu.h"

typedef enum _type_id_101_e {
    M_SP_NA_1 = 1,//single-point information
    M_SP_TA_1 = 2,
    M_DP_NA_1 = 3,//double-point information
    M_DP_TA_1 = 4,
    M_ST_NA_1 = 5,//step position information
    M_ST_TA_1 = 6,
    M_BO_NA_1 = 7,//bitstring of 32 bits
    M_BO_TA_1 = 8,
    M_ME_NA_1 = 9,//measured value, normalized value
    M_ME_TA_1 = 10,
    M_ME_NB_1 = 11,//measured value, scaled value
    M_ME_TB_1 = 12,
    M_ME_NC_1 = 13,//measured value, short floating point number
    M_ME_TC_1 = 14,
    M_IT_NA_1 = 15,//integrated totals
    M_IT_TA_1 = 16,
    M_PS_NA_1 = 20,
    M_ME_ND_1 = 21,

    M_SP_TB_1 = 30,//single-point information with time tag CP56Time2a
    M_DP_TB_1 = 31,//double-point information with time tag CP56Time2a
    M_ST_TB_1 = 32,//step position information with time tag CP56Time2a
    M_BO_TB_1 = 33,//bitstring of 32 bit with time tag CP56Time2a
    M_ME_TD_1 = 34,//measured value, normalized value with time tag CP56Time2a
    M_ME_TE_1 = 35,//measured value, scaled value with time tag CP56Time2a
    M_ME_TF_1 = 36,//measured value, short floating point number with time tag CP56Time2a
    M_IT_TB_1 = 37,//integrated totals with time tag CP56Time2a

    C_SC_NA_1 = 45,//single command
    C_DC_NA_1 = 46,//double command
    C_RC_NA_1 = 47,//regulating step command
    C_SE_NA_1 = 48,//set-point command, normalized value
    C_SE_NB_1 = 49,//set-point command, scaled value
    C_SE_NC_1 = 50,//set-point command, short floating point number
    C_BO_NA_1 = 51,//bitstring of 32 bit

    M_EI_NA_1 = 70,//end of initialization
    C_IC_NA_1 = 100,//interrogation command
    C_CI_NA_1 = 101,//counter interrogation command
    C_RD_NA_1 = 102,//read command
    C_CS_NA_1 = 103,//clock synchronization command
    C_TS_NA_1 = 104,//test command
    C_RP_NA_1 = 105,//reset process command
    C_CD_NA_1 = 106,//delay acquisition command

    P_ME_NA_1 = 110,//parameter of measured values, normalized value
    P_ME_NB_1 = 111,//parameter of measured values, scaled value
    P_ME_NC_1 = 112,//parameter of measured values, short floating point number
    P_AC_NA_1 = 113,//parameter activation
} type_id_101_e;

typedef enum _dpi_e {
    dpi_0, dpi_off, dpi_on, dpi_3
} dpi_e;

typedef struct _quality_descriptor_t {
    _Bool spi: 1;
    _Bool dpi: 1;

    uint8_t _reserve: 1;
    _Bool ei: 1;/** elapsed time valied */
    _Bool bl: 1;/** 1被封锁/0未被封锁 */
    _Bool sb: 1;/** 1被替换/0未被替换 */
    _Bool nt: 1;/** 0当前值/1非当前值 */
    _Bool iv: 1;/** 0有效/1无效 */
}__attribute__((packed)) quality_descriptor_t;

typedef struct _info_obj_addr_t {
    uint16_t tag; //标签号低16bit
    uint8_t tag_mbs; //标签号高8bit
}__attribute__((packed)) info_obj_addr_t;

typedef struct _info_value_q_t {
    quality_descriptor_t qds; //质量描述符
}__attribute__((packed)) info_value_q_t;

typedef struct _info_value_i1_t {
    uint8_t val: 7;
    _Bool t: 1;
    quality_descriptor_t qds;
}__attribute__((packed)) info_value_i1_t;

typedef struct _info_value_i2_t {
    int16_t sval; //normalized|scaled value|sequence counter
    quality_descriptor_t qds;
}__attribute__((packed)) info_value_i2_t;

typedef struct _info_value_i4_t {
    union {
        uint32_t ival;
        float fval; //short floating point number
        char bstr[4]; //binary state information, 32bit
    }__attribute__((packed));

    quality_descriptor_t qds; //质量描述符
}__attribute__((packed)) info_value_i4_t;

typedef struct _cp16time2a_t {
    uint16_t msec;
}__attribute__((packed)) cp16time2a_t;

typedef struct _cp24time2a_t {
    uint16_t msec;
    uint8_t min: 7;
    _Bool iv: 1;
}__attribute__((packed)) cp24time2a_t;

time_t get_cp24time2a(const cp24time2a_t *cp24);

typedef struct _cp32time2a_t {
    uint16_t msec;
    uint8_t min: 7;
    _Bool iv: 1;
    uint8_t hour: 7;
    _Bool su: 1;
}__attribute__((packed)) cp32time2a_t;

time_t get_cp32time2a(const cp32time2a_t *cp32);

typedef struct _cp56time2a_t {
    uint16_t msec;
    uint8_t min: 7;
    _Bool iv: 1;
    uint8_t hour: 7;
    _Bool su: 1;
    uint8_t day;
    uint8_t mon;
    uint8_t year;
}__attribute__((packed)) cp56time2a_t;

time_t get_cp56time2a(const cp56time2a_t *cp56);

void set_cp56time2a(cp56time2a_t *cp56, const time_t t);

#endif //SEQIOT_IEC101_H
